package one.stand.controller;

import com.github.pagehelper.PageHelper;
import com.jmp.base.LiveApi;
import com.jmp.base.dto.*;
import com.jmp.feign.ChatFeign;
import com.jmp.video.VideoClient;
import lombok.extern.slf4j.Slf4j;
import one.stand.advice.ResultEnum;
import one.stand.dto.ConvertUtils;
import one.stand.dto.PageResponse2;
import one.stand.enums.SeeRecordEnums;
import one.stand.mapper.LiveRoomGoodsMapperExt;
import one.stand.mapper.LiveRoomMapperExt;
import one.stand.mapper.LiveUserMapperExt;
import one.stand.model.LiveRoom;
import one.stand.model.LiveRoomGoods;
import one.stand.model.LiveUser;
import one.stand.model.ResultModel;
import one.stand.service.LiveService;
import one.stand.service.RecordPublicService;
import one.stand.util.AssertUtil;
import one.stand.util.DateUtil;
import one.stand.util.OneListUtil;
import one.stand.util.SqlUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@RestController()
@RequestMapping("/")
@Slf4j
public class LiveController implements LiveApi {

    /**
     * 30分钟
     */
    private static long REMAINING_TIME = 15 * 60 * 1000;

    @Autowired
    private ChatFeign chatFeign;

    @Autowired
    private RecordPublicService recordPublicService;

    @Autowired
    private LiveService liveService;
    @Autowired
    private LiveUserMapperExt liveUserMapperExt;
    @Autowired
    private LiveRoomMapperExt liveRoomMapperExt;
    @Autowired
    private LiveRoomGoodsMapperExt liveRoomGoodsMapperExt;

    @Autowired
    private VideoClient videoClient;

    @Override
    public ResultModel<LiveListVo> list(@RequestBody LiveListRequest request) {

        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<LiveRoom> liveRooms;
        if (Objects.nonNull(request.getCardId())) {//我的直播
            liveRooms = liveRoomMapperExt.selectMyList(request.getCardId(), request.getVideoType());
        } else {//直播大厅
            liveRooms = liveRoomMapperExt.selectList(request.getCompanyId(), SqlUtil.like(request.getKeyword()), request.getViewDate());
        }
        PageResponse2<LiveListVo.Live> page = ConvertUtils.page2(liveRooms, liveRoom -> {
            LiveUser liveUser = liveUserMapperExt.selectByPrimaryKey(liveRoom.getLiveUserId());
            return LiveListVo.Live.builder()
                    .roomId(liveRoom.getId())
                    .videoType(liveRoom.getVideoType())
                    .time(liveRoom.getCreateTime())
                    .preTime(liveRoom.getPreTime())
                    .title(liveRoom.getName())
                    .photo(liveRoom.getLiveStatus() == LiveService.LIVE_STATUS_OFF ? liveRoom.getPhoto() : liveRoom.getScreenshotUrl())
                    .status(liveRoom.getLiveStatus())
                    .viewNum(recordPublicService.getPopularity(SeeRecordEnums.LIVE.getCode(), liveRoom.getId()).intValue())
                    .replayUrl(liveRoom.getReplayUrl())
                    .cardId(liveUser.getCardId())
                    .userCurrentRoomId(liveUser.getRoomId())
                    .videoDuration(liveRoom.getVideoDuration())
                    .build();
        });

        LiveListVo vo = LiveListVo.builder()
                .livePage(page)
                .build();
        return ResultModel.success(vo);
    }

    @Override
    public ResultModel save(@RequestBody LiveSaveRequest request) {
        AssertUtil.nonNull(request.getName(), ResultEnum.PARAM_CHECK, "名称不能为空");
        AssertUtil.isTrue(request.getName().length() <= 20, ResultEnum.PARAM_CHECK, "标题文字限制20个以内");
        AssertUtil.nonNull(request.getPhoto(), ResultEnum.PARAM_CHECK, "封面不能为空");
        AssertUtil.nonNull(request.getType(), ResultEnum.PARAM_CHECK, "分类不能为空");

        if (request.getPreFlag() == 1) {//1预告
//            long remainTime = request.getPreTime().getTime() - (new Date()).getTime();
//            AssertUtil.isTrue(remainTime >= REMAINING_TIME, ResultEnum.PARAM_CHECK, "预告时间不能在15分钟内");
        }

        LiveRoom liveRoom = new LiveRoom();
        liveRoom.setType(request.getType());
        liveRoom.setName(request.getName());
        liveRoom.setPhoto(request.getPhoto());
        liveRoom.setPreFlag(request.getPreFlag());
        liveRoom.setPreTime(request.getPreTime());
        liveService.save(request.getCardId(), liveRoom, request.getGoodsIds());

        return ResultModel.success();
    }

    @Override
    public ResultModel<LiveInfoResponse> info(@RequestBody LiveInfoRequest request) {
        Integer cardId = null;
        LiveRoom liveRoom;
        LiveUser liveUser = null;
        if (Objects.isNull(request.getRoomId())) {
            cardId = request.getCardId();
            liveUser = liveUserMapperExt.selectByCardId(request.getCardId());
            liveRoom = Objects.nonNull(liveUser) && Objects.nonNull(liveUser.getRoomId()) ? liveRoomMapperExt.selectByPrimaryKey(liveUser.getRoomId()) : null;
        } else {
            liveRoom = liveRoomMapperExt.selectByPrimaryKey(request.getRoomId());
            if (Objects.nonNull(liveRoom)) {
                liveUser = liveUserMapperExt.selectByPrimaryKey(liveRoom.getLiveUserId());
                cardId = liveUser.getCardId();
            }
        }

        if (Objects.nonNull(liveRoom) && liveRoom.getIsDel() == 0) {
            LiveInfoResponse response = LiveInfoResponse.builder()
                    .hasRoom(true)
                    .videoType(liveRoom.getVideoType())
                    .roomId(liveRoom.getId())
                    .cardId(cardId)
                    .name(liveRoom.getName())
                    .photo(liveRoom.getPhoto())
                    .preFlag(liveRoom.getPreFlag())
                    .preTime(liveRoom.getPreTime())
                    .liveStatus(liveRoom.getLiveStatus())
                    .pullUrl(liveRoom.getPullUrl())
                    .pushUrl(liveRoom.getPushUrl())
                    .videoUrl(liveRoom.getReplayUrl())
                    .screenshotUrl(liveRoom.getScreenshotUrl())
                    .groupId(liveRoom.getGroupId())
                    .viewerNum(recordPublicService.getPopularity(SeeRecordEnums.LIVE.getCode(), liveRoom.getId()).intValue())
                    .viewerPhotos(OneListUtil.toList(liveRoom.getViewerPhotos(), t -> t))
                    .userCurrentRoomId(liveUser.getRoomId())
                    .build();
            return ResultModel.success(response);
        }

        LiveInfoResponse response = LiveInfoResponse.builder()
                .hasRoom(false)
                .build();
        return ResultModel.success(response);
    }

    @Override
    public ResultModel remove(@RequestBody LiveRemoveRequest request) {

        Integer roomId = request.getRoomId();
        if (Objects.isNull(roomId)) {
            LiveUser liveUser = liveUserMapperExt.selectByCardId(request.getCardId());
            if (Objects.isNull(liveUser) || Objects.isNull(liveUser.getRoomId())) {
                log.warn("cardId({}) has no room", request.getCardId());
            } else {
                roomId = liveUser.getRoomId();
            }
        }
        if (Objects.nonNull(roomId)) {
            liveService.remove(roomId);
        }

        return ResultModel.success();
    }

    @Override
    public ResultModel goodsAdd(@RequestBody LiveGoodsAddRequest request) {

        liveService.goodsAdd(request.getCardId(), request.getGoodsIds());

        return ResultModel.success();
    }

    @Override
    public ResultModel goodsUpdate(@RequestBody LiveGoodsUpdateRequest request) {

        liveService.goodsUpdate(request.getRoomGoodsId(), request.getStatus());

        return ResultModel.success();
    }

    @Override
    public ResultModel<LiveGoodsListResponse> goodsList(@RequestBody LiveGoodsListRequest request) {

        Integer roomId = request.getRoomId();
        if (Objects.nonNull(request.getCardId())) {
            LiveUser liveUser = liveUserMapperExt.selectByCardId(request.getCardId());
            roomId = Objects.nonNull(liveUser) && Objects.nonNull(liveUser.getRoomId()) ? liveUser.getRoomId() : null;
        }

        LiveGoodsListResponse response = LiveGoodsListResponse.builder().build();
        if (Objects.nonNull(roomId)) {
            List<LiveRoomGoods> roomGoods = liveRoomGoodsMapperExt.selectByRoomId(roomId, request.getStatus());
            List<LiveGoodsListResponse.Goods> goodsList = ConvertUtils.list(roomGoods, liveRoomGoods -> {
                return LiveGoodsListResponse.Goods.builder()
                        .roomGoodsId(liveRoomGoods.getId())
                        .goodsId(liveRoomGoods.getGoodsId())
                        .status(liveRoomGoods.getStatus())
                        .build();
            });
            response.setGoodsIds(goodsList);
        }

        return ResultModel.success(response);
    }

    @Override
    public ResultModel backView() {
        List<String> groupIds = liveRoomMapperExt.selectGroupIds();
        for (String groupId : groupIds) {
            back(LiveBackRequest.builder().groupId(groupId).build());
        }
        return ResultModel.success();
    }

    @Override
    public ResultModel back(@RequestBody LiveBackRequest request) {

        if (StringUtils.isNoneBlank(request.getGroupId())) {
            ResultModel<ChatGroupInfoVo> resultModel = chatFeign.groupInfo(ChatGroupInfoDto.builder().groupId(request.getGroupId()).build());
            if (resultModel.isSuccess() && resultModel.getData() != null) {
                LiveRoom liveRoom = liveRoomMapperExt.selectByGroupId(request.getGroupId());
                request.setRoomId(liveRoom.getId());
                request.setViewerNum(resultModel.getData().getMemberNum());
                request.setViewerPhotos(resultModel.getData().getMemberPhotos());
            }
        }

        liveService.updateBack(request.getRoomId(), request.getFileId(), request.getReplayUrl(), request.getScreenshotUrl(), request.getViewerNum(), request.getViewerPhotos());

        return ResultModel.success();
    }

    @Override
    public ResultModel<LiveOpenResponse> open(@RequestBody LiveOpenRequest request) {

        LiveUser liveUser = liveUserMapperExt.selectByCardId(request.getCardId());
        AssertUtil.isTrue(Objects.nonNull(liveUser) && Objects.nonNull(liveUser.getRoomId()), ResultEnum.PARAM_CHECK);

        LiveRoom liveRoom = liveService.open(liveUser.getRoomId());

        LiveOpenResponse response = LiveOpenResponse.builder()
                .roomId(liveRoom.getId())
                .pushUrl(liveRoom.getPushUrl())
                .groupId(liveRoom.getGroupId())
                .viewerNum(recordPublicService.getPopularity(SeeRecordEnums.LIVE.getCode(), liveRoom.getId()).intValue())
                .viewerPhotos(OneListUtil.toList(liveRoom.getViewerPhotos(), t -> t))
                .build();
        return ResultModel.success(response);
    }

    @Override
    public ResultModel quit(@RequestBody LiveQuitRequest request) {
        Integer roomId = request.getRoomId();
        if (Objects.nonNull(request.getCardId())) {
            LiveUser liveUser = liveUserMapperExt.selectByCardId(request.getCardId());
            if (Objects.isNull(liveUser) || Objects.isNull(liveUser.getRoomId())) {
                log.warn("cardId{} has no room", request.getCardId());
                return ResultModel.success();
            }
            roomId = liveUser.getRoomId();
        }

        liveService.quit(roomId);

        return ResultModel.success();
    }

    @Override
    public ResultModel timeout(@RequestBody LiveTimeoutRequest request) {
        Date date = DateUtil.getDate(new Date(), Calendar.MINUTE, -request.getTimeout());
        List<LiveRoom> liveRooms = liveRoomMapperExt.selectTimeoutList(DateUtil.format(DateUtil.formatter, date));
        for (LiveRoom liveRoom : liveRooms) {
            liveService.remove(liveRoom.getId());
        }
        List<LiveRoom> endLiveRooms = liveRoomMapperExt.selectEndTimeoutList(DateUtil.format(DateUtil.formatter, date));
        for (LiveRoom liveRoom : endLiveRooms) {
            liveService.quit(liveRoom.getId());
        }
        return ResultModel.success();
    }

    @Override
    public ResultModel end(@RequestBody LiveEndDto request) {
        liveService.end(request.getRoomId(), request.isEnd());
        return ResultModel.success();
    }

    @Override
    public ResultModel<LiveVideoListVo> videoList(@RequestBody LiveVideoListDto request) {

        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<LiveRoom> list = liveRoomMapperExt.selectMyList(request.getCardId(), LiveService.VIDEO_TYPE_VIDEO);
        PageResponse2<LiveVideoListVo.Video> page = ConvertUtils.page2(list, video -> {
            return LiveVideoListVo.Video.builder()
                    .videoId(video.getId())
                    .title(video.getName())
                    .coverUrl(video.getPhoto())
                    .videoUrl(video.getReplayUrl())
                    .status(video.getIsOn())
                    .time(video.getCreateTime().getTime())
                    .videoDuration(video.getVideoDuration())
                    .build();
        });
        LiveVideoListVo vo = LiveVideoListVo.builder()
                .videoPage(page)
                .build();
        return ResultModel.success(vo);
    }

    @Override
    public ResultModel<LiveVideoSaveSignVo> videoSaveSign(@RequestBody LiveVideoSaveSignDto request) {

        String sign = videoClient.getSign(String.valueOf(request.getUserId()));
        AssertUtil.nonNull(sign, ResultEnum.PARAM_CHECK, "获取签名失败");

        LiveVideoSaveSignVo vo = LiveVideoSaveSignVo.builder()
                .sign(sign)
                .build();
        return ResultModel.success(vo);
    }

    @Override
    public ResultModel<LiveVideoSaveNotifyVo> videoSaveNotify() {

        liveService.saveVideoAsync();

        LiveVideoSaveNotifyVo vo = LiveVideoSaveNotifyVo.builder()
                .fileAddNum(0)
                .build();
        return ResultModel.success(vo);
    }

    @Override
    public ResultModel videoUp(@RequestBody LiveVideoUpDto request) {

        liveService.upVideo(request.getId(), request.getTitle());

        return ResultModel.success();
    }
}
